﻿module poseidon.controller.property.prjproperty;

private import dwt.all;
private import poseidon.model.project;
private import poseidon.controller.dialog.generaldialog;
private import poseidon.controller.gui;
private import poseidon.util.waitcursor;
private import poseidon.globals;
private import poseidon.util.miscutil;


class PrjProperty : GeneralDialog
{
	Project project;
	boolean createNew = true;
	private :
	Combo		cobBuildType;
	Text 		txtName, txtDir, txtFilter, txtMainFile, txtExeName, txtExtraCompilerOption, txtObjDir, txtComment, txtPage, txtExeArgs;
	Button 		btnOK, btnDir, btnMainFile, chkEmtyFolder;
	List    	listFiles, listIncludePaths, listLinkLibs, listIgnoreModules;
	Button[30]  btnCompilerOption;
	Button[4] 	btnLibOption;
	bool[30]	compiler_option;

	Composite tab1_Comp, tab2_Comp, tab3_Comp, tab4_Comp;

	
	public this( Shell parent, Project prj )
	{		
		super( parent );
		project = prj;

		// Load compiler_option[]
		if( project )
		{
			int shift = 1, shift_result, comp_result;
		
			for( int i = 0; i < 30; i ++ )
				if( ( project.projectCompilerOption  >> i ) & 1 ) compiler_option[i] = true;
		}
	}
	
	private void initData()
	{
		if( project !is null )
		{
			createNew = false;
			txtName.setText( project.projectName );
			txtDir.setText( project.projectDir );
			txtDir.setEditable( false );
			btnDir.setEnabled( false );
			cobBuildType.select( project.projectBuildType );
			chkEmtyFolder.setSelection(project.showEmptyFolder);

			char[][] files;
			if( project.projectFiles.length > 0 ) files = project.projectFiles;
			if( project.projectInterfaces.length > 0 ) files ~= project.projectInterfaces;
			if( project.projectResources.length > 0 ) files ~= project.projectResources;
			if( project.projectOthers.length > 0 ) files ~= project.projectOthers;
			if( files.length ) listFiles.setItems( files );
			
			if( project.projectIncludePaths.length > 0 ) listIncludePaths.setItems( project.projectIncludePaths );
			if( project.projectLibs.length > 0 ) listLinkLibs.setItems( project.projectLibs );
			if( project.projectIgnoreModules.length > 0 ) listIgnoreModules.setItems( project.projectIgnoreModules );

			
			txtFilter.setText( project.getFilter() );
			txtMainFile.setText( project.mainFile );
			txtExeName.setText( project.projectEXEName );
			txtObjDir.setText( project.projectObjDir );
			txtComment.setText( project.comment );
			txtExeArgs.setText( project.projectEXEArgs );
			txtExtraCompilerOption.setText( project.projectExtraCompilerOption );

			char[][] libOptionText = std.string.split( project.projectLibOption, " " );

			if( project.projectBuildType != 1 )
			{
				for( int i = 0; i < 4; ++ i )
					btnLibOption[i].setEnabled( false );

				txtPage.setEnabled( false );
			}
				

			if( libOptionText.length == 5 )
			{
				for( int i = 0; i < 4; ++ i )
					btnLibOption[i].setSelection( cast(int) std.string.atoi( libOptionText[i] ) );

				if( btnLibOption[3].getEnabled () ) txtPage.setText( libOptionText[4] );
			}
		}
		else
		{
			btnOK.setEnabled( false );
			btnMainFile.setEnabled( false );
		}
		
	}
	
	protected Shell createShell( Shell parent )
	{
		Shell shell = new Shell( parent, DWT.DIALOG_TRIM | DWT.RESIZE | DWT.APPLICATION_MODAL );
		shell.setImage( Globals.getImage( "property" ) );
		
		GridLayout gridLayout = new GridLayout();
 		gridLayout.numColumns = 3;

		with( shell )
		{
			setText( Globals.getTranslation( "pp.title" ));
			setSize( 400, 400 ); 
			shell.setLayout( gridLayout );
		}


		TabFolder tabFolder = new TabFolder( shell, DWT.NONE );
		tabFolder.setLayoutData( new GridData(GridData.FILL, GridData.BEGINNING, true, false, 3, 1 ) );
		

		// TabItem 1:
		tab1_Comp = new Composite( tabFolder, DWT.NONE );

		gridLayout = new GridLayout();
 		gridLayout.numColumns = 5;
 		tab1_Comp.setLayout( gridLayout );

		// Project Name
		with( new Label( tab1_Comp, DWT.NONE ) )setText( Globals.getTranslation( "pp.name" ) );

		with( txtName = new Text( tab1_Comp, DWT.BORDER ) )
		{
			setLayoutData( new GridData(GridData.FILL, GridData.BEGINNING, true, false, 2, 1 ) );
			handleEvent( null, DWT.Modify, &onValidate );
		}		
		// empty_folder filter
		with( chkEmtyFolder = new Button( tab1_Comp, DWT.CHECK ) )
		{
			setText( Globals.getTranslation( "pp.empty_folder" ) );
			setLayoutData( new GridData(GridData.BEGINNING, GridData.CENTER, true, false, 1, 1 ) );
		}
		new Label( tab1_Comp, DWT.NONE );

		// Project Path
		with( new Label( tab1_Comp, DWT.NONE ) ) setText( Globals.getTranslation( "pp.path" ) );

		with( txtDir = new Text( tab1_Comp, DWT.BORDER ) )
		{
			setLayoutData( new GridData( GridData.FILL, GridData.CENTER, true, false, 3, 1 ) );
			handleEvent(null, DWT.Modify, &onValidate);
		}
		with( btnDir = new Button( tab1_Comp, DWT.PUSH ) )
		{
			setText("...");
			setToolTipText( Globals.getTranslation( "pp.browse" ) );
			handleEvent( null, DWT.Selection, &onBrowseDir );
		}

		// Type
		with( new Label( tab1_Comp, DWT.NONE ) ) setText( Globals.getTranslation( "pp.type" ) );
		
		with( cobBuildType = new Combo( tab1_Comp, DWT.BORDER ) )
		{
			add( Globals.getTranslation( "pp.type1" ) );
			//add( "Win32 GUI Application");
			add( Globals.getTranslation( "pp.type2" ) );
			add( Globals.getTranslation( "pp.type3" ) );
			select( 0 );
			setLayoutData( new GridData(GridData.FILL, GridData.CENTER, true, false, 1, 1 ) );
			handleEvent( null, DWT.Modify, &onCoBuildType );
		}
		//new Label( tab1_Comp, DWT.NONE );

		// Filter
		with( new Label( tab1_Comp, DWT.NONE ) ) setText( Globals.getTranslation( "pp.filter" ) );

		with( txtFilter = new Text( tab1_Comp, DWT.BORDER ) )
		{
			setText( "*.d" );
			setToolTipText( Globals.getTranslation( "pp.info_sep" ) );
			setLayoutData(new GridData( GridData.FILL, GridData.CENTER, true, false, 1, 1 ) );
		}
		new Label( tab1_Comp, DWT.NONE );
		

		// Main File
		with( new Label( tab1_Comp, DWT.NONE ) ) setText( Globals.getTranslation( "pp.main_file" ) );
		
		with( txtMainFile = new Text( tab1_Comp, DWT.BORDER ) )
		{
			setLayoutData( new GridData( GridData.FILL, GridData.CENTER, true, false, 3, 1 ) );
			setToolTipText( Globals.getTranslation( "pp.mainfile_tip" ) );
		}
		with( btnMainFile = new Button( tab1_Comp, DWT.PUSH ) )
		{
			setText("...");
			setToolTipText( Globals.getTranslation( "pp.mainfile_browser_tip" ) );
			handleEvent( null, DWT.Selection, &onBrowseMainFile );
		}

		with( new Label( tab1_Comp, DWT.NONE ) ) setText( Globals.getTranslation( "pp.target_name" ) );
		with( txtExeName = new Text( tab1_Comp, DWT.BORDER ) )
		{
			setLayoutData( new GridData( GridData.FILL, GridData.CENTER, true, false, 3, 1 ) );
		}
		new Label( tab1_Comp, DWT.NONE );

		// Obj Path
		with( new Label( tab1_Comp, DWT.NONE ) ) setText( Globals.getTranslation( "pp.obj_path" ) );
		with( txtObjDir = new Text( tab1_Comp, DWT.BORDER ) )
		{
			setText("objs");
			setLayoutData( new GridData( GridData.FILL, GridData.CENTER, true, false, 3, 1 ) );
		}
		new Label( tab1_Comp, DWT.NONE );

		
		// Comment
		with( new Label( tab1_Comp, DWT.NONE ) ) setText( Globals.getTranslation( "pp.comment" ) );
		with( txtComment = new Text( tab1_Comp, DWT.BORDER | DWT.MULTI | DWT.V_SCROLL | DWT.WRAP ) )
		{
			scope color = new Color( display, 0, 0x66, 0 );
			setForeground( color );
			GridData innergridData = new GridData( GridData.FILL, GridData.BEGINNING, true, false, 3, 1 );
			Font font = new Font( display, "Verdana", 9, DWT.NORMAL );
			setFont( font );
			innergridData.heightHint = 42;
			setLayoutData( innergridData );
		}
		new Label( tab1_Comp, DWT.NONE );

		
		Group fileListGroup = new Group( tab1_Comp, DWT.NONE );
		fileListGroup.setText( Globals.getTranslation( "pp.filelist" ) );
		gridLayout = new GridLayout();
		gridLayout.numColumns = 2;
		fileListGroup.setLayout( gridLayout );
		GridData gridData = new GridData( GridData.FILL_HORIZONTAL );
		gridData.horizontalSpan = 5;
		fileListGroup.setLayoutData( gridData );
		
		
		with( listFiles = new List( fileListGroup, DWT.BORDER | DWT.MULTI | DWT.V_SCROLL ) )
		{
			GridData innergridData = new GridData( GridData.FILL, GridData.BEGINNING, true, false, 1, 5 );
			Font font = new Font( display, "Verdana", 8, DWT.NORMAL );
			setFont( font );
			
			int ListHeight = getItemHeight() * 9;
			Rectangle trim = computeTrim( 0, 0, 0, ListHeight );
			innergridData.heightHint = trim.height;
			setLayoutData( innergridData );
		}
		
		with( new Button( fileListGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("add_obj") );
			setToolTipText( Globals.getTranslation( "pp.add" ) );
			handleEvent( null, DWT.Selection, &onEdit0_0 );
		}

		with( new Button( fileListGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("delete_obj") );
			setToolTipText( Globals.getTranslation( "pp.delete" ) );
			handleEvent( null, DWT.Selection, &onEdit0_1 );
		}

		with( new Button( fileListGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("write_obj") );
			setToolTipText( Globals.getTranslation( "pp.edit" ) );
			handleEvent( null, DWT.Selection, &onEdit0_2 );
		}

		with( new Button( fileListGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("importfile") );
			setToolTipText( Globals.getTranslation( "pp.importall" ) );
			handleEvent( null, DWT.Selection, &onEdit0_3 );
		}
		/*
		with( new Button( fileListGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("next_nav") );
			handleEvent( null, DWT.Selection, &onEdit0_4 );
		}
		*/
		// ********************************************************************
		// TabItem 2( Include & Libs ):

		
		tab2_Comp = new Composite( tabFolder, DWT.NONE );

		
		gridLayout = new GridLayout();
 		gridLayout.numColumns = 3;
 		tab2_Comp.setLayout( gridLayout );

		// Directory
		Group directoryGroup = new Group( tab2_Comp, DWT.NONE );
		
		gridData = new GridData( GridData.FILL_HORIZONTAL );
		gridData.horizontalSpan = 3;
		directoryGroup.setLayoutData( gridData );
				
		directoryGroup.setText( Globals.getTranslation( "pp1.directory" ) );
		gridLayout = new GridLayout();
		gridLayout.numColumns = 2;
		directoryGroup.setLayout( gridLayout );


		
		with( listIncludePaths = new List( directoryGroup, DWT.BORDER | DWT.MULTI | DWT.V_SCROLL ) )
		{
			GridData innergridData = new GridData( GridData.FILL, GridData.BEGINNING, true, false, 1, 5 );
			Font font = new Font( display, "Verdana", 8, DWT.NORMAL );
			setFont( font );
			
			int ListHeight = getItemHeight() * 11;
			Rectangle trim = computeTrim( 0, 0, 0, ListHeight );
			innergridData.heightHint = trim.height;
			setLayoutData( innergridData );
		}
		
		with( new Button( directoryGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("add_obj") );
			setToolTipText( Globals.getTranslation( "pp.add" ) );
			handleEvent( null, DWT.Selection, &onEdit1_0 );
		}

		with( new Button( directoryGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("delete_obj") );
			setToolTipText( Globals.getTranslation( "pp.delete" ) );
			handleEvent( null, DWT.Selection, &onEdit1_1 );
		}

		with( new Button( directoryGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("write_obj") );
			setToolTipText( Globals.getTranslation( "pp.edit" ) );
			handleEvent( null, DWT.Selection, &onEdit1_2 );
		}

		with( new Button( directoryGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("prev_nav") );
			setToolTipText( Globals.getTranslation( "pp.moveup" ) );
			handleEvent( null, DWT.Selection, &onEdit1_3 );
		}

		with( new Button( directoryGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("next_nav") );
			setToolTipText( Globals.getTranslation( "pp.movedown" ) );
			handleEvent( null, DWT.Selection, &onEdit1_4 );
		}		


		// Library
		Group libsGroup = new Group( tab2_Comp, DWT.NONE );
		libsGroup.setText( Globals.getTranslation( "pp1.library" ) );
		gridLayout = new GridLayout();
		gridLayout.numColumns = 2;
		libsGroup.setLayout( gridLayout );
			
		gridData = new GridData( GridData.FILL_HORIZONTAL );
		gridData.horizontalSpan = 3;
		libsGroup.setLayoutData( gridData );

		with( listLinkLibs = new List( libsGroup, DWT.BORDER | DWT.MULTI | DWT.V_SCROLL ) )
		{
			GridData innergridData = new GridData( GridData.FILL, GridData.BEGINNING, true, false, 1, 5 );
			Font font = new Font( display, "Verdana", 8, DWT.NORMAL );
			setFont( font );
			
			int ListHeight = getItemHeight() * 11;
			Rectangle trim = computeTrim( 0, 0, 0, ListHeight );
			innergridData.heightHint = trim.height;
			setLayoutData( innergridData );
		}		

		
		with( new Button( libsGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("add_obj") );
			setToolTipText( Globals.getTranslation( "pp.add" ) );
			handleEvent( null, DWT.Selection, &onEdit2_0 );
		}

		with( new Button( libsGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("delete_obj") );
			setToolTipText( Globals.getTranslation( "pp.delete" ) );
			handleEvent( null, DWT.Selection, &onEdit2_1 );
		}

		with( new Button( libsGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("write_obj") );
			setToolTipText( Globals.getTranslation( "pp.edit" ) );
			handleEvent( null, DWT.Selection, &onEdit2_2 );
		}

		with( new Button( libsGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("prev_nav") );
			setToolTipText( Globals.getTranslation( "pp.moveup" ) );
			handleEvent( null, DWT.Selection, &onEdit2_3 );
		}

		with( new Button( libsGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("next_nav") );
			setToolTipText( Globals.getTranslation( "pp.movedown" ) );
			handleEvent( null, DWT.Selection, &onEdit2_4 );
		}	

		// ********************************************************************
		// TabItem 3( Complier Options ):

		
		tab3_Comp = new Composite( tabFolder, DWT.NONE );

		gridLayout = new GridLayout();
 		gridLayout.numColumns = 4;
		//gridLayout.makeColumnsEqualWidth = true;
 		tab3_Comp.setLayout( gridLayout );

		createCheckBox( Globals.getTranslation( "pp2.o0" ), compiler_option[0], tab3_Comp, 0, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o1" ), compiler_option[1], tab3_Comp, 1, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o2" ), compiler_option[2], tab3_Comp, 2, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o3" ), compiler_option[3], tab3_Comp, 3, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o4" ), compiler_option[4], tab3_Comp, 4, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o5" ), compiler_option[5], tab3_Comp, 5, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o6" ), compiler_option[6], tab3_Comp, 6, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o7" ), compiler_option[7], tab3_Comp, 7, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o8" ), compiler_option[8], tab3_Comp, 8, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o9" ), compiler_option[9], tab3_Comp, 9, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o10" ), compiler_option[10], tab3_Comp, 10, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o11" ), compiler_option[11], tab3_Comp, 11, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o12" ), compiler_option[12], tab3_Comp, 12, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o13" ), compiler_option[13], tab3_Comp, 13, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o14" ), compiler_option[14], tab3_Comp, 14, 2 );
		createCheckBox( Globals.getTranslation( "pp2.o15" ), compiler_option[15], tab3_Comp, 15, 2 );


		// horizontal line
		with( new Label( tab3_Comp, DWT.SEPARATOR | DWT.HORIZONTAL ) )
			setLayoutData( new GridData( GridData.FILL, GridData.CENTER, true, false, 4, 1 ) );


		with( new Label( tab3_Comp, DWT.NONE ) )
		{
			setText( Globals.getTranslation( "pp2.extra" ) );
			setLayoutData( new GridData( GridData.FILL, GridData.BEGINNING, true, false, 4, 1 ) );
		}

		with( txtExtraCompilerOption = new Text( tab3_Comp, DWT.BORDER | DWT.MULTI | DWT.V_SCROLL | DWT.WRAP )) 
		{
			scope font = new Font( display, "Verdana", 8, DWT.NORMAL );
			setFont( font );
			setLayoutData( new GridData( GridData.FILL, GridData.FILL, true, true, 4, 1) );
		}


		// horizontal line
		with( new Label( tab3_Comp, DWT.SEPARATOR | DWT.HORIZONTAL ) )
			setLayoutData( new GridData( GridData.FILL, GridData.CENTER, true, false, 4, 1 ) );		

			
		with( new Label( tab3_Comp, DWT.NONE ) )
		{
			setText( Globals.getTranslation( "pp2.lib_label" ) );
			setLayoutData( new GridData( GridData.FILL, GridData.BEGINNING, true, false, 4, 1 ) );
		}

		with( btnLibOption[0] = new Button( tab3_Comp, DWT.CHECK ) )
		{
			setText( Globals.getTranslation( "pp2.lib_o0" ) );
			setLayoutData( new GridData( GridData.BEGINNING, GridData.CENTER, true, false, 2, 1 ) );
		}
		
		with( btnLibOption[1] = new Button( tab3_Comp, DWT.CHECK ) )
		{
			setText( Globals.getTranslation( "pp2.lib_o1" ) );
			setLayoutData( new GridData( GridData.BEGINNING, GridData.CENTER, true, false, 2, 1 ) );
		}


		with( btnLibOption[2] = new Button( tab3_Comp, DWT.CHECK ) )
		{
			setText( Globals.getTranslation( "pp2.lib_o2" ) );
			setLayoutData( new GridData( GridData.BEGINNING, GridData.CENTER, true, false, 2, 1 ) );
		}		


		with( btnLibOption[3] = new Button( tab3_Comp, DWT.CHECK ) )
		{
			setText( Globals.getTranslation( "pp2.lib_o3" ) );
			setLayoutData( new GridData( GridData.BEGINNING, GridData.CENTER, true, false, 1, 1 ) );
		}

		with( txtPage = new Text( tab3_Comp, DWT.BORDER ) )
		{
			setLayoutData( new GridData( GridData.FILL, GridData.BEGINNING, true, false, 1, 1 ) );
		}

		// horizontal line
		with( new Label( tab3_Comp, DWT.SEPARATOR | DWT.HORIZONTAL ) )
			setLayoutData( new GridData( GridData.FILL, GridData.CENTER, true, false, 4, 1 ) );	
		
		with( new Label( tab3_Comp, DWT.NONE ) )
		{
			setText( Globals.getTranslation( "pp2.args" ) );
			setLayoutData( new GridData( GridData.FILL, GridData.BEGINNING, true, false, 4, 1 ) );
		}

		with( txtExeArgs = new Text( tab3_Comp, DWT.BORDER | DWT.MULTI | DWT.V_SCROLL | DWT.WRAP )) 
		{
			scope font = new Font( display, "Verdana", 8, DWT.NORMAL );
			setFont( font );
			setLayoutData( new GridData( GridData.FILL, GridData.FILL, true, true, 4, 1) );
		}

        tab4_Comp = new Composite( tabFolder, DWT.NONE );
        gridLayout = new GridLayout();
        gridLayout.numColumns = 2;
		tab4_Comp.setLayout( gridLayout );

		createCheckBox( Globals.getTranslation( "pp3.o0" ), compiler_option[16], tab4_Comp, 16, 1 );
		createCheckBox( Globals.getTranslation( "pp3.o1" ), compiler_option[17], tab4_Comp, 17, 1 );
		createCheckBox( Globals.getTranslation( "pp3.o2" ), compiler_option[18], tab4_Comp, 18, 1 );
		createCheckBox( Globals.getTranslation( "pp3.o3" ), compiler_option[19], tab4_Comp, 19, 1 );
		createCheckBox( Globals.getTranslation( "pp3.o4" ), compiler_option[20], tab4_Comp, 20, 1 );
		createCheckBox( Globals.getTranslation( "pp3.o5" ), compiler_option[21], tab4_Comp, 21, 1 );
		createCheckBox( Globals.getTranslation( "pp3.o6" ), compiler_option[22], tab4_Comp, 22, 1 );
		createCheckBox( Globals.getTranslation( "pp3.o7" ), compiler_option[23], tab4_Comp, 23, 1 );
		createCheckBox( Globals.getTranslation( "pp3.o8" ), compiler_option[24], tab4_Comp, 24, 1 );
		createCheckBox( Globals.getTranslation( "pp3.o9" ), compiler_option[25], tab4_Comp, 25, 1 );
		createCheckBox( Globals.getTranslation( "pp3.o10" ), compiler_option[27], tab4_Comp, 27, 1 );
		createCheckBox( Globals.getTranslation( "pp3.o11" ), compiler_option[28], tab4_Comp, 28, 1 );
		createCheckBox( Globals.getTranslation( "pp3.o12" ), compiler_option[26], tab4_Comp, 26, 2 );
		createCheckBox( Globals.getTranslation( "pp3.o13" ), compiler_option[29], tab4_Comp, 29, 2 );

		with( new Label( tab4_Comp, DWT.SEPARATOR | DWT.HORIZONTAL ) )
			setLayoutData( new GridData( GridData.FILL, GridData.CENTER, true, false, 2, 1 ) );

		Group ignoreModuleGroup = new Group( tab4_Comp, DWT.NONE );
      
		gridData = new GridData( GridData.FILL_HORIZONTAL );
		gridData.horizontalSpan = 2;
		ignoreModuleGroup.setLayoutData( gridData );
            
		ignoreModuleGroup.setText( Globals.getTranslation( "pp3.ignore" ) );
		gridLayout = new GridLayout();
		gridLayout.numColumns = 2;
		ignoreModuleGroup.setLayout( gridLayout );

		with( listIgnoreModules = new List( ignoreModuleGroup, DWT.BORDER | DWT.MULTI | DWT.V_SCROLL ) )
		{
			GridData innergridData = new GridData( GridData.FILL, GridData.CENTER, true, false, 1, 5 );
			scope font = new Font( display, "Verdana", 8, DWT.NORMAL );
			setFont( font );
			int ListHeight = getItemHeight() * 11;
			Rectangle trim = computeTrim( 0, 0, 0, ListHeight );
			innergridData.heightHint = trim.height;
			setLayoutData( innergridData );
		}       

		with( new Button( ignoreModuleGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("add_obj") );
			setToolTipText( Globals.getTranslation( "pp.add" ) );
			handleEvent( null, DWT.Selection, &onEdit3_0 );
		}

		with( new Button( ignoreModuleGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("delete_obj") );
			setToolTipText( Globals.getTranslation( "pp.delete" ) );
			handleEvent( null, DWT.Selection, &onEdit3_1 );
		}

		with( new Button( ignoreModuleGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("write_obj") );
			setToolTipText( Globals.getTranslation( "pp.edit" ) );
			handleEvent( null, DWT.Selection, &onEdit3_2 );
		}

		with( new Button( ignoreModuleGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("prev_nav") );
			setToolTipText( Globals.getTranslation( "pp.moveup" ) );
			handleEvent( null, DWT.Selection, &onEdit3_3 );
		}

		with( new Button( ignoreModuleGroup, DWT.FLAT ) )
		{
			setImage( Globals.getImage("next_nav") );
			setToolTipText( Globals.getTranslation( "pp.movedown" ) );
			handleEvent( null, DWT.Selection, &onEdit3_4 );
		}   
		
		TabItem item1 = new TabItem( tabFolder, DWT.NONE );
		item1.setText( Globals.getTranslation( "pp.folder" ) );
		item1.setControl( tab1_Comp );

		TabItem item2 = new TabItem( tabFolder, DWT.NONE );
		item2.setText( Globals.getTranslation( "pp1.folder" ) );
		item2.setControl( tab2_Comp );

		TabItem item3 = new TabItem( tabFolder, DWT.NONE );
		item3.setText( Globals.getTranslation( "pp2.folder" ) );
		item3.setControl( tab3_Comp );

		TabItem item4 = new TabItem( tabFolder, DWT.NONE );
		item4.setText( Globals.getTranslation( "pp3.folder" ) );
		item4.setControl( tab4_Comp );

		// horizontal line
		with( new Label( shell, DWT.SEPARATOR | DWT.HORIZONTAL ) )
			setLayoutData( new GridData( GridData.FILL, GridData.FILL, true, false, 3, 1 ) );
		
		// the bottom buttton bar
		Button[] buts = createButtonBar( shell );
		btnOK = buts[0];
		btnOK.handleSelection( this, delegate( SelectionEvent e )
		{
			PrjProperty pThis = cast(PrjProperty)e.cData;
			pThis.onOK(e);
		} 
		);
		
		
		initData();
		
		shell.pack();
		Point pt = shell.getSize();
		pt.x = pt.y * 4 / 3;// * 3 / 2;
		shell.setSize(pt);
		shell.setMinimumSize(pt);

		return shell;


	}

	private void createCheckBox(char[] langId, bool initVal, Composite composite = null, int num = 0, int gridNum = 1 )
	{
		with( btnCompilerOption[num] = new Button( composite, DWT.CHECK ) )
		{
			setText( langId );
			setSelection( initVal );
			setLayoutData( new GridData( GridData.BEGINNING, GridData.CENTER, true, false, gridNum, 1 ) );
		}
	}

	private void onCoBuildType( Event e )
	{
		if( cobBuildType.getSelectionIndex() == 1 )
		{
			for( int i = 0; i < 4; ++ i )
				btnLibOption[i].setEnabled( true );

			txtPage.setEnabled( true );
		}
		else
		{
			for( int i = 0; i < 4; ++ i )
				btnLibOption[i].setEnabled( false );

			txtPage.setEnabled( false );
		}
	}

	// only when create new project
	private void onBrowseDir(Event e) {
		scope wc = new WaitCursor(shell);
		scope dlg = new DirectoryDialog(shell, DWT.OPEN);
		dlg.setFilterPath(Globals.recentDir);
		char[] fullpath = dlg.open();
		if( fullpath )
		{
			if( sGUI.packageExp.isProjectOpened( fullpath ) ) 
			{
				MessageBox.showMessage(Globals.getTranslation("mb.prj_already_opened"), Globals.getTranslation( "INFORMATION"), 
					getShell(), DWT.ICON_WARNING);
				return;
			}
			
			char[] file = std.path.join(fullpath, Project.EXT);
			if(std.file.exists(file))
			{
				int result = MessageBox.showMessage(Globals.getTranslation("mb.choose_prj_file_exist"), Globals.getTranslation("mb.file_exists"), 
					getShell(), DWT.ICON_QUESTION | DWT.YES | DWT.NO | DWT.CANCEL);
				if(result == DWT.YES){
					this.project = Project.loadProject(fullpath);
					initData();
					// 
					createNew = true;
				}else if(result == DWT.NO){
					txtDir.setText(fullpath);
				}
				// DWT.CANCEL do nothing
				
			}else{
				txtDir.setText(fullpath);
			}
		}
	}
	
	private void onBrowseMainFile(Event e) {
		// nested class
		class _Dlg : GeneralDialog {
			List list;
			char[] dir;
			char[] filter;
			Button btnOK, btnCancel;
			this(Shell parent, char[] dir, char[] filter){
				super(parent);
				this.dir = dir;
				this.filter = filter;				
			}

			private char[][] findDFiles( char[] BaseRootDir )
			{
				char[][] fullPaths;

				// Nested Function
				void _lookFile( char[] rootDir )
				{
					char[][] listDir = std.file.listdir( rootDir, filter );
					foreach( char[] s; listDir )
					{
						char[] fullPath = std.path.join( rootDir, s );
						if( std.file.isfile( fullPath ) )
							fullPaths ~= fullPath;
						else
							_lookFile( fullPath );
						
					}
				}

				_lookFile( BaseRootDir );

				return fullPaths;
			}
			
			
			protected Shell createShell(Shell parent) {
				Shell shell = new Shell(parent, DWT.RESIZE | DWT.DIALOG_TRIM | DWT.APPLICATION_MODAL);				
				shell.setText("Select the main file");
				shell.setLayout(new GridLayout(2,false));
				list = new List(shell, DWT.V_SCROLL | DWT.BORDER | DWT.SINGLE);
				list.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1));
				// Note, the event is different from btnOK's onOK(Event e)
				list.handleEvent(null, DWT.DefaultSelection, &onOK);

				char[][] listDFile = findDFiles( dir );
				foreach( char[] s; listDFile )
				{
					char[] path = MiscUtil.relativePath( s, dir );
					list.add(path);
				}

				/*
				Search search = new Search(dir, filter, RECLS_FLAG.RECLS_F_RECURSIVE);
				foreach(Entry entry; search){
					char[] path = MiscUtil.relativePath(entry.Path(), dir);
					list.add(path);
				}
				*/
				
				// btns[0] is OK button, btns[1] is Cancel button
				Button[] btns = createButtonBar(shell);
				shell.setDefaultButton(btns[0]);
				btns[0].handleEvent(null, DWT.Selection, &onOK);
				
				shell.pack();
				Point pt = shell.getSize();
				shell.setSize(pt.x + 20, pt.x);

				return shell;
			}
			protected void onOK(Event e) {
				int sel = list.getSelectionIndex();
				if(sel >= 0){
					result = list.getItem(sel);
				}				
				getShell().close();
			}
		}
		char[] dir = txtDir.getText();
		char[] filter = txtFilter.getText(); //fixed to "d", the std.recls refuse "*.d;*.xml"???
		scope dlg = new _Dlg(getShell(), dir, filter);
		char[] result = dlg.open();
		if(result)
			txtMainFile.setText(result);
	}

	private char[] getFullPath( char[] filename )
	{
		char[] dirName		= std.string.strip( std.path.getDirName( filename ) );
		char[] driveName 	= std.string.strip( std.path.getDrive( filename ) );

		if( driveName.length > 0 )
			return filename;
		else
			return std.string.strip( txtDir.getText() ) ~ "\\" ~ filename;
	}
		
	
	protected void onOK(SelectionEvent e) {
		char[] dir = txtDir.getText();
		
		// Windows system will remove any space at the both end of the dir
		dir = std.string.strip(dir);
		txtDir.setText(dir);
		
		if(!Project.checkDir(dir)){
			MessageBox.showMessage(Globals.getTranslation("mb.root_as_prjdir"));
			return;
		}
		if(createNew && sGUI.packageExp.isProjectOpened(dir)) {
			MessageBox.showMessage(Globals.getTranslation("mb.prj_already_opened"), Globals.getTranslation("INFORMATION"), 
				getShell(), DWT.ICON_WARNING);
			return;
		}

		
		boolean save = true;
		if( project is null )
		{
			// create new project
			project = new Project( dir );
			char[] newLibDir = dir ~ "\\objs";

			if( !std.file.exists( newLibDir ) ) std.file.mkdir( newLibDir );
		}else
		{
			// the project is opened as dir not opened from project file,
			// prompt to save
			char[] path = std.path.join( project.projectDir, Project.EXT );
			if(!std.file.exists(path)){
				char[] s = Globals.getTranslation("mb.prompt _save_prj");
				int result = MessageBox.showMessage(s, Globals.getTranslation("QUESTION"),
					getShell(), DWT.YES | DWT.NO | DWT.CANCEL | DWT.ICON_QUESTION);
				if(DWT.CANCEL == result)	
					return;
				if(DWT.YES != result)
					save = false;				
			}
		}
		
		project.projectName 		= std.string.strip( txtName.getText() );
		project.projectBuildType 	= cobBuildType.getSelectionIndex();
		project.projectEXEName 		= std.string.strip( txtExeName.getText() );
		project.projectEXEArgs		= std.string.strip( txtExeArgs.getText() );
		project.comment				= std.string.strip( txtComment.getText() );
		project.setFileFilter( txtFilter.getText() );
		project.showEmptyFolder = chkEmtyFolder.getSelection();
		project.mainFile = txtMainFile.getText();
		project.projectObjDir = std.string.strip( txtObjDir.getText() );

		for( int i = 0; i < 30; i ++ )
			compiler_option[i] = cast(bool) btnCompilerOption[i].getSelection();

		project.transCompilerOptionHSU( compiler_option );
		project.projectExtraCompilerOption 	= txtExtraCompilerOption.getText();

		project.projectFiles.length = project.projectInterfaces.length = project.projectResources.length = project.projectOthers.length =
		project.projectIncludePaths.length = project.projectLibs.length = project.projectIgnoreModules.length = 0;

		// all files
		foreach( char[] s; listFiles.getItems() )
		{
			if( std.string.tolower( std.path.getExt( s ) ) == "d" )
				project.projectFiles ~= getFullPath( s );
			else if( std.string.tolower( std.path.getExt( s ) ) == "di" )
				project.projectInterfaces ~= getFullPath( s );
			else if( std.string.tolower( std.path.getExt( s ) ) == "res" )
				project.projectResources ~= getFullPath( s );
			else
				project.projectOthers ~= getFullPath( s );
		}

		// include path
		foreach( char[] s; listIncludePaths.getItems() )
			project.projectIncludePaths ~= getFullPath( s );

		// link libraries
		foreach( char[] s; listLinkLibs.getItems() )
			project.projectLibs ~= getFullPath( s );

		// link libraries
		foreach( char[] s; listIgnoreModules.getItems() )
			project.projectIgnoreModules ~= s;

		project.buildOptionLib = project.projectLibOption = null;
		for( int i = 0; i < 4; ++i )
		{
			bool bSelect;
			if( btnLibOption[i].getSelection() )
			{
				project.projectLibOption ~= "1 ";
				bSelect = true;
			}
			else
				project.projectLibOption ~= "0 ";
				
			switch( i )
			{
				case 0:
					if( bSelect ) project.buildOptionLib ~= "-l "; break;
				case 1:
					if( bSelect ) project.buildOptionLib ~= "-n "; break;
				case 2:
					if( bSelect ) project.buildOptionLib ~= "-i "; break;
				case 3:
					if( bSelect )
					{
						int numPage = std.string.atoi( txtPage.getText() );
						if( numPage > 0 ) 
						{
							if( !( numPage & ( numPage - 1 ) ) ) project.buildOptionLib ~= ( "-p" ~ std.string.toString( numPage ) ~ " " );
						}
					}
					
					break;
				default:
					break;
			}
		}

		char[] page = std.string.strip( txtPage.getText() );
		if( page.length ) project.projectLibOption ~= page; else project.projectLibOption ~= "16";

		
		// save to file
		if( save ) 
		{
			project.save();
			sAutoComplete.refreshFileParser( sGUI.packageExp.getActiveProjectFiles );
		}
		
		result = "OK";
		// close the dialog
		getShell().close();
	}
	
	private void onValidate(Event e) {
		boolean bName = false;
		boolean bDir = true;
		
		char[] str;
		str = txtName.getText();
		bName = (std.string.strip(str).length != 0);
			
		str = txtDir.getText();
		if( !std.file.exists(str) || !std.file.isdir(str))
			bDir = false;
		
		btnOK.setEnabled(bName && bDir);
		btnMainFile.setEnabled(bDir);		
	}
	
	private void swapListItem( List activeList, int a, int b )
	{
		with( activeList )
		{
			char[] temp = getItem( a );
			setItem( a, getItem( b ) );
			setItem( b, temp );
			setSelection( b );
		}
	}

	private bool hasSelect( List activeList )
	{
		if( activeList.getItemCount() == 0 ) return false;
		if( activeList.getFocusIndex() == -1 ) return false;
		if( activeList.getSelectionCount == 0 ) return false;

		return true;
	}
	
	private void touchAdd( List activeList, char[] str )
	{
		if( !str.length ) return;

		char[][] files = std.string.split( str, ";" );
		foreach( char[] s; files )
			activeList.add( s );
			
		activeList.setTopIndex( activeList.getItemCount());
		activeList.deselectAll();
		activeList.select( activeList.getItemCount() - files.length ,activeList.getItemCount() - 1 );		
	}

	private void touchDel( List activeList )
	{
		if( hasSelect( activeList ) )
			activeList.remove( activeList.getSelectionIndices() );
	}

	private void touchEdit( List activeList, char[] str )
	{
		if( !str.length ) return;

		int index = activeList.getFocusIndex();
		activeList.setItem( index, str );
		activeList.deselectAll();
		activeList.select( index );
	}
	

	private void onEdit0_0( Event e )
	{
		scope dlg = new _editDlg( getShell(), 1, 2, Globals.getTranslation( "diag.title0" ) );
		touchAdd( listFiles, dlg.open() );
	}

	private void onEdit0_1( Event e ){ touchDel( listFiles ); }

	private void onEdit0_2( Event e )
	{
		if( hasSelect( listFiles ) )
		{
			scope dlg = new _editDlg( getShell(), 2, 2, Globals.getTranslation( "diag.title0_1" ), listFiles.getItem( listFiles.getFocusIndex() ) );
			touchEdit( listFiles, dlg.open() );
		}
	}

	private void onEdit0_3( Event e )
	{
		char[] dir;
		
		if( project )
			dir = project.projectDir;
		else
		{
			try
			{
				dir = std.string.strip( txtDir.getText() );
				if( !std.file.isdir( dir ) ) return;
			}
			catch
			{
				return;
			}
		}

		listFiles.removeAll();
				
		char[][] files = sGUI.packageExp.getAllFilesInProjectDir( dir, 1 );
		foreach( char[] s; files )
			listFiles.add( s );

		listFiles.selectAll();
	}

	//listIncludePaths, listLinkLibs;

	private void onEdit1_0( Event e )
	{
		scope dlg = new _editDlg( getShell(), 0, 0, Globals.getTranslation( "diag.title1" ) );
		touchAdd( listIncludePaths, dlg.open() );
	}

	private void onEdit1_1( Event e ){ touchDel( listIncludePaths ); }

	private void onEdit1_2( Event e )
	{
		if( hasSelect( listIncludePaths ) )
		{
			scope dlg = new _editDlg( getShell(), 0, 0, Globals.getTranslation( "diag.title1_1" ), listIncludePaths.getItem( listIncludePaths.getFocusIndex() ) );
			touchEdit( listIncludePaths, dlg.open() ); 
		}
	}

	private void onEdit1_3( Event e )
	{
		with( listIncludePaths )
		{
			if( getItemCount() == 0 ) return;
			if( getFocusIndex() == -1 ) return;
			if( getSelectionCount() == 0 ) return;
			
			int index = getSelectionIndex();
			if( index <= 0 )
				return;
			else
				swapListItem( listIncludePaths, index, index - 1 );
		}
	}

	private void onEdit1_4( Event e )
	{
		with( listIncludePaths )
		{
			if( getItemCount() == 0 ) return;
			if( getFocusIndex() == -1 ) return;
			if( getSelectionCount() == 0 ) return;
			
			int index = getSelectionIndex();
			if( getItemCount() <= index )
				return;
			else
				swapListItem( listIncludePaths, index, index + 1 );
		}
	}	
	
	private void onEdit2_0( Event e )
	{
		scope dlg = new _editDlg( getShell(), 1, 1, Globals.getTranslation( "diag.title2" ) );
		touchAdd( listLinkLibs, dlg.open() );
	}

	private void onEdit2_1( Event e ){ touchDel( listLinkLibs ); }

	private void onEdit2_2( Event e )
	{
		if( hasSelect( listLinkLibs ) )
		{
			scope dlg = new _editDlg( getShell(), 2, 1, Globals.getTranslation( "diag.title2_1" ), listLinkLibs.getItem( listLinkLibs.getFocusIndex() ) );
			touchEdit( listLinkLibs, dlg.open() ); 
		}
	}
	
	private void onEdit2_3( Event e )
	{
		with( listLinkLibs )
		{
			if( getItemCount() == 0 ) return;
			if( getFocusIndex() == -1 ) return;
			if( getSelectionCount() == 0 ) return;
			
			int index = getSelectionIndex();
			if( index <= 0 )
				return;
			else
				swapListItem( listLinkLibs, index, index - 1 );
		}
	}

	private void onEdit2_4( Event e )
	{
		with( listLinkLibs )
		{
			if( getItemCount() == 0 ) return;
			if( getFocusIndex() == -1 ) return;
			if( getSelectionCount() == 0 ) return;
			
			int index = getSelectionIndex();
			if( getItemCount() <= index )
				return;
			else
				swapListItem( listLinkLibs, index, index + 1 );
		}
	}

	private void onEdit3_0( Event e )
	{
		scope dlg = new _editDlg( getShell(), -1, 1, "Add Ignore Module..." );
		touchAdd( listIgnoreModules, dlg.open() );
	}

	private void onEdit3_1( Event e ){ touchDel( listIgnoreModules ); }

	private void onEdit3_2( Event e )
	{
		if( hasSelect( listIgnoreModules ) )
		{
			scope dlg = new _editDlg( getShell(), -1, 1, "Edit Ignore Module", listIgnoreModules.getItem( listIgnoreModules.getFocusIndex() ) );
			touchEdit( listIgnoreModules, dlg.open() );
		}       
	}

	private void onEdit3_3( Event e )
	{
		with( listIgnoreModules )
		{
			if( getItemCount() == 0 ) return;
			if( getFocusIndex() == -1 ) return;
			if( getSelectionCount() == 0 ) return;

			int index = getSelectionIndex();
			if( index <= 0 )
				return;
			else
				swapListItem( listIgnoreModules, index, index - 1 );
			}
	}

	private void onEdit3_4( Event e )
	{
		with( listIgnoreModules )
		{
            if( getItemCount() == 0 ) return;
            if( getFocusIndex() == -1 ) return;
			if( getSelectionCount() == 0 ) return;

			int index = getSelectionIndex();
			if( getItemCount() <= index )
				return;
			else
				swapListItem( listIgnoreModules, index, index + 1 );
		}
	}           
}